package com.team24.hotel.controller.common;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.team24.hotel.domain.Order;
import com.team24.hotel.service.OrderService;
import com.team24.hotel.utils.OrderIdGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Controller
@RequestMapping("/alipay")
public class Alipay {
    // 应用ID,您的APPID，收款账号既是您的APPID对应支付宝账号
    public static String app_id = "2016100100642047";

    // 商户私钥，您的PKCS8格式RSA2私钥
    public static String merchant_private_key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCrsoAGjZV1h6wdzeGShkdgoduFuUwHE00C8koizACCnUg9NQtjj3PtSB6kUSVKU05ZqxtD4c7xK3JKpE5CwdlqtrSjVr2/2cEjS/oBzvo1mQrOvCkfLN4r2eDYUtsZ8ii82P2sGvYjoc5uYmN+nFY0dx0j7NsxmJU6JttQG8LnzYua55oDooXBu7agDKzlqOLHAsqZev0080bcnge98dvBmb0ThIL0l57LzxhjLt0yq0VsTGaWrjB4euZvQeSN0bN+RlLplNItg2voOLxiq4qEyz0pmlu7xEz7fsjKdRgmj1G/JJO8E0wKV34wzdVsHAdqIooyv8Ia+xaXZfKq58CNAgMBAAECggEANU5e9ynf/DRaGIrB/NbZtEOsPxEvbIbugvqsT69cfTDNq8sbNRblnAanFMbot/GzQp2gAmxJ7pBZlJj8fzdmA/6jiI62rKizkPzWqtcS0a8pLtQ2RCqO87haWW8n/R80zKTl5Rgd0SQ8TgMX9sgc738Hug6gYv6HXh2QO4fS9FpU6lbGd2Ymb+K7ZYSRZTdEaWF24wls1jLRpQ3aL/9pEwQrlEwZzLabsslvZAGvWNbZQ1x5tUFkzIZE6sofzJEE8NefH3n8VvrFon7g8nhmXg7zwgufaApwNt+molZG9x5wKgEHy/5IYmS1CIK91EJiRMnYPubSLw0/NN4OhTrY4QKBgQD92OavPo06vKhvXxGAOuBaFzs0juHiVrWMGoZrvkpQARQk42rRa289PH393yh6Z5n9EgooWzJZlVVDRS58rayh1SKo7+ezDenSuDMuXyx83hiijQKJkuQU6BJ5DvdsmWdmahGVpZgI8tedfGwxt9DYM87tJlSWlSsQBDR4Im6zRQKBgQCtJ0CiHvJRZfcEKj8XdQNrxz7+51PekZkDBDpenUh9fdkq0mIc0oQ8JkIEEHx19g6GpFfYUuwUg3ZX7M1oBJI1e4k/xZllUTVQf+vyBXEtgJVqrOgf0XXJhDhEYkM2MmLshaMbHQ+LmrAV4n8GrAZbGFSU8vcKLsrGnudN+khIqQKBgAHk4WvDUrhyeetC0VWcmtnxPG7a9hKDRR2DgSdCpzlLmMPhsoVXgN/7GJGRXbL0HPEHdm3wqEKE27sBxCQIA7a9aWHLUHZEj08UMsWQzjssSRDFbpRqNSt2w9SFaRE1X9Eiz3jHYIgIj9VL/V6tmXBTiqK4W384I7cd4OpYj2zlAoGAKPcdan2p1Kor+7dG//S2H3yfIc124TRPIBCTAqlxagcpJuFpRupjUJu4iJ+h4oKZQy+EfPB5XA0SJZEns5FJSg/1E7pbJUZGN8pb9wFkmmBOeVN5A3YZyNhYO42H2z2me9DOGu8QK3YobLUOWnS+eDTUZfzph2Y0oTMdBCzPhykCgYEAu0Y3qK8Wrwe8pz/ZgSzxGYzK25un/BNMLYMO/AKtoXps7zZtN4IXR8/8eAaoXmY4UlNURVhimV5p/Okq9x5BgmbtsyPDheJ/SlwVwBDVbgSDHkhsZPwbUX2mbCTVdo7gs8skpg6LEtSPAMfeeVQhiPaVX1VaONZHjjG6mBIb9eM=";

    // 支付宝公钥,查看地址：https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
    public static String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmGyiy/3taGDvTiPe5poUWEq3P9JOU0NaTMUB6eDlK4F5a9V4odjKm3X/xMUNwt9Iou4/Pf8CSyjuDMp4cLqaq/HYWzStmyBEkiY2IJM1vyI8gYBPvzbGnE2tdpwmaaEoV5r+V4FzvL0sqkqqo3YWhJC+bpAs0Aa+Hpe0JXeJDWPsW1WkBmCOESsL87XnEOIdMQmbBzv/ND/bKisjqS1xG8Jkeh+RMD5IM12sR0KsMs1IP4R3yqeXHRSYsruhlAf5e6rypb8Rv5mk3zACXCw/LJzuXE5wZy15joKZ+VevIlLSpc8rDfJuvOST8htDUQtoDo7cg1S1v3uxG8cFGdpbswIDAQAB";

    // 服务器异步通知页面路径 需http://格式的完整路径，不能加?id=123这类自定义参数，必须外网可以正常访问
    public static String notify_url = "http://110.184.82.180/alipay/notifyUrl";

    // 页面跳转同步通知页面路径 需http://格式的完整路径，不能加?id=123这类自定义参数，必须外网可以正常访问
    public static String return_url = "http://localhost:8080/alipay/returnUrl";

    // 签名方式
    public static String sign_type = "RSA2";

    // 字符编码格式
    public static String charset = "utf-8";

    //沙箱网关
    public static String gatewayUrl ="https://openapi.alipaydev.com/gateway.do";

    // 仅支持JSON
    public static String format = "JSON";

    @Autowired
    private OrderService orderService;

    @RequestMapping(value = "/pay")
    public void pay(HttpServletRequest httpRequest, HttpServletResponse httpResponse, Order order)
            throws ServletException, IOException {
        AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, app_id, merchant_private_key, format, charset,
                alipay_public_key, sign_type); // 获得初始化的AlipayClient
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();// 创建API对应的request
        alipayRequest.setReturnUrl(return_url);
        alipayRequest.setNotifyUrl(notify_url);// 在公共参数中设置回跳和通知地址
        alipayRequest.setBizContent("{" + "    \"out_trade_no\":\""+order.getOrderId()+"\","
                + "    \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," + "    \"total_amount\":"+order.getOrderPrize()+","
                + "    \"subject\":\""+order.getOrderHotel()+order.getOrderRoom()+"\"," + "    \"body\":\""+order.getOrderHotel()+order.getOrderRoom()+"\","
                + "    \"passback_params\":\"merchantBizType%3d3C%26merchantBizNo%3d2016010101111\","
                + "    \"extend_params\":{" + "    \"sys_service_provider_id\":\"2088511833207846\"" + "    }" + "  }");// 填充业务参数
        String form = "";
        try {
            form = alipayClient.pageExecute(alipayRequest).getBody(); // 调用SDK生成表单
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        httpResponse.setContentType("text/html;charset=" + charset);
        httpResponse.getWriter().write(form);// 直接将完整的表单html输出到页面
        httpResponse.getWriter().flush();
        httpResponse.getWriter().close();
        System.out.println("pay---------------------");
        //网速不足会出现问题，所以将业务逻辑临时写在这
        order.setOrderStatus(1);
        orderService.saveOrUpdate(order);
    }

    @RequestMapping("/refund")
    @ResponseBody
    public String alipayrefund(String orderId){

        Order order = orderService.findByPrimaryKey(orderId);
        //商户订单号和支付宝交易号不能同时为空。 trade_no、  out_trade_no如果同时存在优先取trade_no
        //商户订单号，和支付宝交易号二选一
        String out_trade_no = orderId;
        //支付宝交易号，和商户订单号二选一
//        String trade_no ="此处推荐从数据库获取订单号";
        //退款金额，不能大于订单总金额
        String refund_amount = order.getOrderPrize().toString();
        //退款的原因说明
        String refund_reason = "不想买了";
        //标识一次退款请求，同一笔交易多次退款需要保证唯一，如需部分退款，则此参数必传。
        String  out_request_no = OrderIdGenerator.getRefundId();
        /**********************/
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        AlipayClient client = new DefaultAlipayClient(gatewayUrl, app_id, merchant_private_key, format, charset,
                alipay_public_key, sign_type);
        AlipayTradeRefundRequest alipay_request = new AlipayTradeRefundRequest();

        AlipayTradeRefundModel model=new AlipayTradeRefundModel();
        model.setOutTradeNo(out_trade_no);
//        model.setTradeNo(trade_no);
        model.setRefundAmount(refund_amount);
        model.setRefundReason(refund_reason);
        model.setOutRequestNo(out_request_no);
        alipay_request.setBizModel(model);

        AlipayTradeRefundResponse alipay_response = null;
        try {
            alipay_response = client.execute(alipay_request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        if(alipay_response.getCode().equals("10000")){
            //退款成功后的业务逻辑
            order.setOrderStatus(99);
            orderService.saveOrUpdate(order);
            System.out.println("已经退款");
            return "退款成功";
        }else {
            //退款失败的业务逻辑
            return "退款失败";
        }
    }

    @RequestMapping(value = "/returnUrl")
    public String returnUrl(HttpServletRequest request, RedirectAttributes redirectAttributes)
            throws IOException, AlipayApiException {
        System.out.println("=================================同步回调=====================================");

        // 获取支付宝GET过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        System.out.println(params);
        boolean signVerified =  AlipaySignature.rsaCheckV1(params, alipay_public_key, charset, sign_type);

        // ——请在这里编写您的程序（以下代码仅作参考）——
        if (signVerified) {
            // 商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
            // 支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
            // 付款金额
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");

            System.out.println("商户订单号="+out_trade_no);
            System.out.println("支付宝交易号="+trade_no);
            System.out.println("付款金额="+total_amount);

            Order order = orderService.findByPrimaryKey(out_trade_no);
            order.setOrderPrize((int)Double.parseDouble(total_amount));
            order.setOrderStatus(1);
            orderService.saveOrUpdate(order);

            redirectAttributes.addAttribute("id",out_trade_no);
            return "redirect:/frontOrders/selectByOrderId";

        } else {
            return "payFail";
        }
    }

    @RequestMapping(value = "/notifyUrl")
    public void notifyUrl(HttpServletRequest request, HttpServletResponse response)
            throws AlipayApiException, IOException {
        System.out.println("#################################异步回调######################################");

        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        System.out.println(params);
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipay_public_key, charset, sign_type); // 调用SDK验证签名

        // ——请在这里编写您的程序（以下代码仅作参考）——

        /*
         * 实际验证过程建议商户务必添加以下校验： 1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
         * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额）， 3、校验通知中的seller_id（或者seller_email)
         * 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
         * 4、验证app_id是否为该商户本身。
         */
        if (signVerified) {// 验证成功
            // 商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");

            // 支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");

            // 交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");

            System.out.println("商户订单号="+out_trade_no);
            System.out.println("支付宝交易号="+trade_no);
            System.out.println("交易状态="+trade_status);
            if (trade_status.equals("TRADE_FINISHED")) {
                // 判断该笔订单是否在商户网站中已经做过处理
                // 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                // 如果有做过处理，不执行商户的业务程序
                System.out.println("FINISH");
                // 注意：
                // 退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
            } else if (trade_status.equals("TRADE_SUCCESS")) {
                // 判断该笔订单是否在商户网站中已经做过处理
                // 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                // 如果有做过处理，不执行商户的业务程序
                System.out.println("SUCCESS");
                // 注意：
                // 付款完成后，支付宝系统发送该交易状态通知
            }

            System.out.println("异步回调验证成功");
            response.getWriter().write("success");

        } else {// 验证失败
            System.out.println("异步回调验证失败");
            response.getWriter().write("fail");

            // 调试用，写文本函数记录程序运行情况是否正常
            // String sWord = AlipaySignature.getSignCheckContentV1(params);
            // AlipayConfig.logResult(sWord);
        }
        response.getWriter().flush();
        response.getWriter().close();
    }


}
